YUI.add('wfmodel', function (Y) {
	
	function ProjectSync(){//和外部存储同步用,保证先外部，然后才是modellist。
		
	    function save() {
	        Y.localStorage && Y.localStorage.setItem(Y.localKey, Y.JSON.stringify(Y.totalData.getValuesByKey()));
	    }
	    
	    function set(model) {
	    	var needSave = false;
	        var hash        = model.toJSON(),
	            idAttribute = model.idAttribute;
	        
	        if (!Y.Lang.isValue(hash[idAttribute])) {
	            hash[idAttribute] = uuid.v4();
	            
		        if(hash['dp'] == 'nop'){//如果model的dp不是nop，那么uid和dp对象的uid一致。
		        	if(Y.loginUser){
		        		hash['uid'] = Y.loginUser.id;
		        	}else{
		        		hash['uid'] = -1;//impossible
		        	}
		        }else{
		        	var dpr = Y.totalDataHash[hash['dp']];
		        	if(dpr){
			        	var uid = dpr.getValue('uid');
			        	hash['uid'] = uid;
		        	}
		        }
		        
	            var c = Y.clone(hash,true);
	            c['action'] = 'add';
	            c['mid'] = hash[idAttribute];
//	            c['uid'] = hash['uid'];
	            Y.changeHistory.add(c);
	            Y.localData.add(hash);
	            Y.totalData.add(hash);
	            if(Y.someItemData){
	            	Y.someItemData.add(hash);
	            }
	            needSave = true;
	        }else{
	        	var r = Y.localDataHash[hash[idAttribute]];
	        	var r1 = Y.totalDataHash[hash[idAttribute]];
	        	if(r){//有可能已经删除，但是blur动作可能触发这段代码。
		        	r.set('data',hash);
		        	r1.set('data',hash);
		        	Y.localData.update(r);//返回更新后的record
		        	Y.totalData.update(r1);
		            if(Y.someItemData){
		            	var r2 = Y.someItemDataHash[hash[idAttribute]];
		            	if(r2){
		            		r2.set('data',hash);
		            		Y.someItemData.update(r2);
		            	}
		            }
		        	needSave = true;
	        	}
	        }
	        if(needSave)save();
	        return hash;
	    }
	    
	    function destroy(id) {//这里是操作外部存储。
	    	var modelHash;
	    	var r = Y.totalDataHash[id];
	    	if(r){
	    		modelHash = r.get('data');
	            var c = Y.clone(modelHash,true);
	            c['action'] = 'delete';
	            c['mid'] = id;
	            c['uid'] = r.getValue('uid');
	            Y.changeHistory.add(c);
	    		Y.localDataHash[id] = null;
	    		Y.totalDataHash[id] = null;
	            if(Y.someItemDataHash){
	            	Y.someItemDataHash[id] = null;
	            }
	    		save();
	    	}
	        return modelHash;
	    }
		
	    return function (action, options, callback) {
	        // `this` refers to the Model or ModelList instance to which this sync
	        // method is attached.
	        switch (action) {
	        case 'create': // intentional fallthru
	        case 'update':
	            callback(null, set(this));
	            return;
	        case 'read':
	        	alert('reading');
	            callback(null, Y.localDataHash[this.get('id')]);
	            return;
	        case 'delete':
	            callback(null, destroy(this.get('id')));
	            return;
	        }
	    };
	}
	
	function ProjectListSync(){
	    return function (action, options, callback) {
		    if (action === 'read') {
		    	var pid = options.parentId;
		    	if(!pid)pid = Y.rootEntry;
		    	var subset = Y.localData.filter.filter("dp", pid);
		    	callback(null,subset.getValuesByKey());
		    } else {
		    	callback('Unsupported sync action: ' + action);
		    }
	    };
	}
	
	Y.namespace('AppModel');
	Y.AppModel.ProjectModel = Y.Base.create('projectModel', Y.Model, [], {
	    // This tells the Model to use a localStorage sync provider (which we'll
	    // create below) to save and load information about a project item.
		sync: ProjectSync(),
		hasParent: function () {
			return this.get('dp') != Y.rootEntry;
		},
		getParent:function(){
			if(this.hasParent){
				return Y.Wfutils.getModelById(this.get('dp'));
			}else{
				return null;
			}
		},
		canEdit:function(){
			if(Y.loginUser && this.get('uid') == Y.loginUser.id){
				return true;
			}
			if(!Y.loginUser && !Y.sharedMode){//没有登录，也不是shareMode可以。
				return true;
			}
			if(this.get('shareType') == 'public-editable'){
				return true;
			}
			return false;
		},
		
		canDelete:function(){
			if(Y.loginUser && this.get('uid') == Y.loginUser.id){
				return true;
			}
			if(!Y.loginUser && !Y.sharedMode){//没有登录，也不是shareMode可以。
				return true;
			}
			return false;
		},
		getParents:function(){
			var parents = [];
			var model = this;
			while(model.hasParent()){
				var p = model.getParent();
				parents.push(p);
				model = p;
			}
			return parents;
		},
		hasChildren:function(){
			var list = Y.projectListList[this.get('id')];
			return list && list.size()>0;
		},
		getLastDeepestOpenChild:function(){
			var model = this;
			var children = [];
			while(model.hasChildren() && model.get('open')){
				var clist = Y.projectListList[model.get('id')];
				var cmodel = clist.lastModel();
				children.push(cmodel);
				model = cmodel;
			}
			return children;
		},
		idAttribute: 'uuid'
		}, {
			ATTRS: {
		        // Indicates whether or not this project item has been completedd.
		        uuid: {},
		        uid:{value:0},
		        title:{value:''},
		        note:{value:''},
		        path:{value:''},
		        dp:{value:Y.rootEntry},
		        done:{value:false},
		        position:{value:0},
		        open:{value:false},
		        shareType:{value:'none'}
		    }
		});
	
		Y.AppModel.ProjectList = Y.Base.create('projectList', Y.ModelList, [], {
			    // This tells the list that it will hold instances of the ProjectModel class.
			    model: Y.AppModel.ProjectModel,
			    step : 131072,
			    // This tells the list to use a localStorage sync provider (which we'll
			    // create below) to load the list of Project items.
			    sync: ProjectListSync(),
			    // Returns an array of all models in this list with the `dn` attribute
			    // set to `true`.
			    completed: function () {
			        return Y.Array.filter(this.toArray(), function (model) {
			            return model.get('dn');
			        });
			    },
			    firstModel:function(){
			    	return this.item(0);
			    },
			    lastModel:function(){
			    	return this.item(this.size() - 1);
			    },
			    next: function (model) {
			    	var index = this.indexOf(model);
			    	if(index === -1 || index === this.size() - 1)return null;
			    	return this.item(index + 1);
			    },
			    previous:function(model){
			    	var index = this.indexOf(model);
			    	if(index < 1)return null;
			    	return this.item(index - 1);
			    },
			    nextPosition:function(model){
			    	if(!model)return this.step;
			    	var next = this.next(model);
			    	if(next){
			    		var min = model.get('position');
			    		var max = next.get('position');
			    		if((max - min) > 1){
			    			return min + (max-min)/2;
			    		}else{
			    			this.resetOrder();
			    			return this.nextPosition(model);
			    		}
			    	}else{
			    		return model.get('position') + this.step;
			    	}
			    },
			    prevPosition:function(model){
			    	var previous = this.previous(model);
			    	if(previous){
			    		var min = previous.get('position');
			    		var max = model.get('position');
			    		if((max - min) > 1){
			    			return min + (max-min)/2;
			    		}else{
			    			this.resetOrder();
			    			return this.prevPosition(model);
			    		}
			    	}else{
						if(model.get('position') > 1){
							return model.get('position')/2;
						}else{
							this.resetOrder();
							return this.step/2;
						}
			    	}
			    },
				resetOrder:function(){
					var step = this.step;
					this.each(function(item){
						item.set('position',step).save();
						step += this.step;
					});
				}
			});
},'0.0.1',{requires:['base','model', 'model-list']});